#/usr/bin/python
#coding: utf-8 -*-

'''
Alogrithme du glouton pour la rÃ©solution du problÃ¨me d'approvisionnement des villes de WOW par les entrepots.
'''

import logging
from Tracer import *


class GloutonSolver(object):
	def __init__(self, Topo = None):
		self.topology = Topo
		self.total_cost = 0
		self.glouton()
	
	''' Retourne la ville dont le nom est "city_name"'''
	def getCity(self, city_name):
		for city in self.topology.cities:
			if city.name == city_name:
				return city
		return False
		
	''' MAJ des besoins de chacune des villes.'''
	def updateCityNeeds(self, warehouse):
		# Selection des routes en provenance de l'entrepot
		logging.debug('Selection des routes en provenance de l\'entrepot ' + warehouse.name)
		warehouse_roads = []
		for road in self.topology.roads:
			if road.warehouse == warehouse.name:
				warehouse_roads.append(road)
				
		# On tri les routes suivant le cout de transport (du - au + Ã©levÃ©)
		logging.debug('Tri des routes suivant le cout de transport (du - au + élevé)')
		warehouse_roads.sort(lambda r1,r2:cmp(r1.cost, r2.cost))
		for road in warehouse_roads:
			logging.debug('Ville "' + road.city + '" | cout transport : ' + str(road.cost))

		# MAJ des besoins des villes si nécessaire
		logging.debug('MAJ des besoins des villes si nécessaire')
		for road in warehouse_roads:
			city = self.getCity(road.city)
			logging.debug('Ville "' + city.name + '" | besoin : ' + str(city.current_needs))
			if city.current_needs > 0:
				# On satisfait au maximum la demande de la ville
				transferred = self.topology.transit(road.warehouse, road.city, city.current_needs)
				# MAJ du cout total
				self.total_cost += (road.cost * transferred)
				self.topology.tracer.append(Tracer(Tracer.TRANSPORT, road.warehouse, road.city, (road.cost * transferred)))

			# break si entrepot vide
			if warehouse.is_empty():
				logging.debug('Entrepot "' + warehouse.name +'" vide')
				break

	''' Check s'il reste encore des villes dans le besoin'''
	def isCitiesInNeed(self):
		for city in self.topology.cities:
			if city.current_needs > 0:
				return True
		return False

	''' Algo du glouton'''
	def glouton(self):
		# Tri des entrepots suivant leurs coûts de construction
		logging.info('Tri des entrepots suivant leurs couts de construction')
		self.topology.warehouses.sort(lambda w1,w2:cmp(w1.cost, w2.cost))
		logging.debug('Entrepots tries :')

		for wh in self.topology.warehouses:
        		logging.debug('Entrepot "' + wh.name + '" | cout : ' + str(wh.cost))

	        for wh in self.topology.warehouses:
			# Check s'il reste encore des villes dans le besoin
			if self.isCitiesInNeed():
				# CrÃ©ation de l'entrepot
				logging.info('Création de l\'entrepot ' + wh.name)
				self.topology.tracer.append(Tracer(Tracer.CREATION, wh.name, cost=wh.cost))
				self.topology.createWarehouse(wh.name)
				
				# MAJ des besoins de chaque ville
				logging.info('Mise à jour des besoins de chacune des villes associées à  l\'entrepot ' + wh.name)
				self.updateCityNeeds(wh)
			else:
				# Les besoins de toutes les villes sont satisfait. Fin de l'algo
				break

		logging.info('**** Recapitulatif des entrepots crees ****')

		for wh in self.topology.constructedWarehouses:
			logging.info('Entrepot "' + wh.name + '" | cout : ' + str(wh.cost))
			self.total_cost += wh.cost
		logging.info('Cout obtenu : ' + str(self.total_cost))
		for trace in self.topology.tracer:
			print trace.display()
		print 'Cout obtenu : ' + str(self.total_cost)

